﻿using System;
using System.IO;
using System.Management;

namespace HorrorsOfArkham.Game_Application_Layer
{
    public class HorrorsGameAppHandler : GameAppHandler
    {
        #region Members

        /*
         * PLACEHOLDERS
         * 
        public GameLogicHandler mGameLogicHandler
        {
            get;
        }

        public GameViewHandler mGameViewHandler
        {
            get;
        }
        */

        public static readonly HorrorsGameAppHandler Instance = new HorrorsGameAppHandler();

        //Values used in initialization
        const long STORAGE_SPACE_NEEDED_AS_BYTES = 200000;
        const long PHYSICAL_MEMORY_NEEDED = 200000;
        const long VIRTUAL_MEMORY_NEEDED = 100000;

        #endregion

        #region Initialization

        protected HorrorsGameAppHandler()
        { 
        }

        /// <summary>
        /// Method which initializes all systems before game is started
        /// </summary>
        /// <param name="uniqueGameAppID">Unique game ID</param>
        /// <returns>true/false, whether initialization is successful</returns>
        public bool InitInstance(string uniqueGameAppID)
        {
            bool initOK = false;

            initOK = setLogFileDirectory();
            if (!initOK)
            {
                Logger.Instance.DebugLine("Setting up log file directory failed.");
                return false;
            }
            else
            {
                Logger.Instance.DebugLine("Setting up log file directory succesful.");
            }

            initOK = CheckOnlyInstance(uniqueGameAppID);
            if (!initOK)
            {
                Console.WriteLine("OnlyInstance check failed.");
                return false;
            }
            else
            {
                Console.WriteLine("OnlyInstance check succesful.");
            }

            initOK = CheckStorageSpace();
            if (!initOK)
            {
                Console.WriteLine("Storage space check failed.");
                return false;
            }
            else
            {
                Console.WriteLine("Storage space check succesful.");
            }

            initOK = CheckMemory();
            if (!initOK)
            {
                Console.WriteLine("Memory check failed.");
                return false;
            }
            else
            {
                Console.WriteLine("Memory check succesful.");
            }

            //PLACEHOLDER
            //calculateCPUSpeed();
            //loadResourceCache();

            initOK = LoadStrings();
            if (!initOK)
            {
                Console.WriteLine("String loading failed.");
                return false;
            }
            else
            {
                Console.WriteLine("String loading succesful.");
            }

            initOK = createLUAScriptManager();
            if (!initOK)
            {
                Console.WriteLine("Initializing LUA Manager failed.");
                return false;
            }
            else
            {
                Console.WriteLine("Initializing LUA Manager succesful.");
            }


            initOK = createEventManager();
            if (!initOK)
            {
                Console.WriteLine("Initializing Event Manager failed.");
                return false;
            }
            else
            {
                Console.WriteLine("Initializing Event Manager succesful.");
            }

            //PLACEHOLDERS
            //loadGameOptions();
            //mGameLogicHandler.Instance.InitGameLogic;
            //mGameViewHandler.Instance.InitGameView;

            initOK = setTempFileDirectory();
            if (!initOK)
            {
                Console.WriteLine("Setting up temp file directory failed.");
                return false;
            }
            else
            {
                Console.WriteLine("Setting up temp file directory succesful.");
            }


            initOK = setSaveFileDirectory();
            if (!initOK)
            {
                Console.WriteLine("Setting up save file directory failed.");
                return false;
            }
            else
            {
                Console.WriteLine("Setting up save file directory succesful.");
            }

            //preloadInitialResources();

            return true;
        }

        #endregion

        #region Individual Init Methods

        /// <summary>
        /// Check log file directory and create it if it is not found
        /// </summary>
        /// <returns>true/false</returns>
        private bool setLogFileDirectory()
        {
            bool directoryFound = false;

            directoryFound = Logger.Instance.SetLogFileDirectory();

            return directoryFound;
        }

        /// <summary>
        /// Checks whether current instance of the game is the only one
        /// </summary>
        /// <param name="uniqueGameAppID">Game ID, unique to the machine</param>
        /// <returns>true/false</returns>
        private bool CheckOnlyInstance(string uniqueGameAppID)
        {
            bool onlyInstance;

            var mutex = new System.Threading.Mutex(true, uniqueGameAppID, out onlyInstance);

            return onlyInstance;
        }

        /// <summary>
        /// Checks if there is enough free storage space in the currently used directory
        /// </summary>
        /// <returns>true/false</returns>
        private bool CheckStorageSpace()
        {
            bool enoughSpaceFound = false;

            string currentDir = Directory.GetCurrentDirectory();

            string currentDisk = currentDir.Substring(0,3);

            DriveInfo[] allDrives = DriveInfo.GetDrives();

            foreach (DriveInfo d in allDrives)
            {
                if (d.RootDirectory.Root.ToString().Equals(currentDisk))
                {
                    if (d.IsReady == true)
                    {
                        if (d.AvailableFreeSpace >= STORAGE_SPACE_NEEDED_AS_BYTES)
                        {
                            enoughSpaceFound = true;
                        }
                    }
                }
            }

            return enoughSpaceFound;
        }

        /// <summary>
        /// Checks if there is enough free memory for the game
        /// </summary>
        /// <returns>true/false</returns>
        private bool CheckMemory()
        {
            bool enoughMemoryFound = false;

            ObjectQuery winQuery = new ObjectQuery("SELECT * FROM CIM_OperatingSystem");

            ManagementObjectSearcher searcher = new ManagementObjectSearcher(winQuery);

            foreach (ManagementObject item in searcher.Get())
            {
                if ((UInt64)item["TotalVisibleMemorySize"] > (UInt64)PHYSICAL_MEMORY_NEEDED)
                {
                    if ((UInt64)item["FreeVirtualMemory"] > (UInt64)VIRTUAL_MEMORY_NEEDED)
                    {
                        enoughMemoryFound = true;
                    }
                    else 
                    {
                        Console.WriteLine("Not enough free virtual memory.");
                    }
                }
                else
                {
                    Console.WriteLine("Not enough physical memory.");
                }
            }

            return enoughMemoryFound;
        }

        /// <summary>
        /// Load main strings for the game from XML
        /// </summary>
        /// <returns>true/false</returns>
        private bool LoadStrings()
        {
            bool stringsLoaded = false;

            stringsLoaded = XMLResourceLoader.Instance.LoadXMLFromFile("XML/mainStrings.xml", XMLType.STRING);

            return stringsLoaded;
        }

        /// <summary>
        /// Initialize LUA script manager
        /// </summary>
        /// <returns>true/false</returns>
        private bool createLUAScriptManager()
        {
            bool managerCreated = false;

            managerCreated = LUAScriptHandler.Instance.Initialize();

            return managerCreated;
        }

        /// <summary>
        /// Initialize event manager
        /// </summary>
        /// <returns>true/false</returns>
        private bool createEventManager()
        {
            bool managerCreated = false;

            managerCreated = EventHandler.Instance.Initialize();

            return managerCreated;
        }

        /// <summary>
        /// Check temp file directory and create it if it is not found
        /// </summary>
        /// <returns>true/false</returns>
        private bool setTempFileDirectory()
        {
            bool directoryFound = false;

            directoryFound = TempFileHandler.Instance.SetTempFileDirectory();

            return directoryFound;
        }

        /// <summary>
        /// Check save file directory and create it if it is not found
        /// </summary>
        /// <returns>true/false</returns>
        private bool setSaveFileDirectory()
        {
            bool directoryFound = false;

            directoryFound = SaveFileHandler.Instance.SetSaveFileDirectory();

            return directoryFound;
        }

        #endregion
    }
}
